package com.bsoft.utils;

import cn.hutool.core.collection.ListUtil;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * URL转PDF → ZIP压缩 → Base64编码 工具类
 */
public class UrlToPdfToZipToBase64Util {

    /**
     * 步骤1：单个URL转PDF，返回PDF字节数组
     * @param url 目标URL
     * @return PDF字节数组
     * @throws Exception 异常
     */
    public static byte[] urlToPdf(String url) throws Exception {
        // 1. HtmlUnit模拟浏览器加载URL（解决JS渲染问题）
        try (WebClient webClient = new WebClient()) {
            // 配置WebClient：禁用CSS/JS报错、启用JS渲染
            webClient.getOptions().setCssEnabled(true);
            webClient.getOptions().setJavaScriptEnabled(true);
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
            webClient.waitForBackgroundJavaScript(3000); // 等待JS渲染完成（3秒）

            // 2. 获取渲染后的HTML页面
            HtmlPage page = webClient.getPage(url);
            String htmlContent = page.asXml(); // 转为XHTML（Flying Saucer要求XHTML格式）

            // 3. Flying Saucer将HTML渲染为PDF
            ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocumentFromString(htmlContent);
            renderer.layout();
            renderer.createPDF(pdfOut);

            return pdfOut.toByteArray();
        }
    }

    /**
     * 步骤2：多PDF字节数组压缩为ZIP，返回ZIP字节数组
     * @param pdfBytesList PDF字节数组列表（每个元素对应一个PDF）
     * @param pdfNames PDF文件名列表（如["invoice1.pdf", "invoice2.pdf"]）
     * @return ZIP字节数组
     * @throws Exception 异常
     */
    public static byte[] pdfsToZip(List<byte[]> pdfBytesList, List<String> pdfNames) throws Exception {
        if (pdfBytesList.size() != pdfNames.size()) {
            throw new IllegalArgumentException("PDF数量与文件名数量不匹配");
        }

        ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
        try (ZipOutputStream zos = new ZipOutputStream(zipOut, StandardCharsets.UTF_8)) {
            for (int i = 0; i < pdfBytesList.size(); i++) {
                byte[] pdfBytes = pdfBytesList.get(i);
                String pdfName = pdfNames.get(i);

                // 创建ZIP条目（文件名）
                ZipEntry entry = new ZipEntry(pdfName);
                zos.putNextEntry(entry);

                // 写入PDF字节数组
                zos.write(pdfBytes);
                zos.closeEntry(); // 关闭当前条目
            }
        }
        return zipOut.toByteArray();
    }

    /**
     * 步骤3：ZIP字节数组转Base64字符串
     * @param zipBytes ZIP字节数组
     * @return Base64编码字符串
     */
    public static String zipToBase64(byte[] zipBytes) {
        // JDK8+自带Base64工具类（避免第三方依赖）
        return Base64.getEncoder().encodeToString(zipBytes);
    }

    /**
     * 完整流程：多URL → 多PDF → ZIP → Base64
     * @param urls URL列表
     * @param pdfNames PDF文件名列表
     * @return Base64编码的ZIP字符串
     * @throws Exception 异常
     */
    public static String urlListToBase64Zip(List<String> urls, List<String> pdfNames) throws Exception {
        // 1. 批量URL转PDF
        List<byte[]> pdfBytesList = new java.util.ArrayList<>();
        for (String url : urls) {
            pdfBytesList.add(urlToPdf(url));
        }

        // 2. 多PDF压缩为ZIP
        byte[] zipBytes = pdfsToZip(pdfBytesList, pdfNames);

        // 3. ZIP转Base64
        return zipToBase64(zipBytes);
    }

    // 测试主方法
    public static void main(String[] args) throws Exception {
        // 测试URL列表（替换为你的实际URL）
        List<String> urls = ListUtil.of(
                "https://www.chinaebill.cn/eips-wxapp-service/H5FinanceDisplay/showInvoice?invoice_code=51060125&invoice_number=0116258300&check_code=8175dd&app_id=Ke8XxUStK&security=33A71D047AA1B6AFDF0B9B979A68B360",
                "https://www.chinaebill.cn/eips-wxapp-service/H5FinanceDisplay/showInvoice?invoice_code=51060125&invoice_number=0116258301&check_code=8175dd&app_id=Ke8XxUStK&security=33A71D047AA1B6AFDF0B9B979A68B360"
        );

        // PDF文件名列表（自定义，建议有辨识度）
        List<String> pdfNames = ListUtil.of("invoice_01.pdf", "invoice_02.pdf");

        // 执行完整流程
        String base64Zip = urlListToBase64Zip(urls, pdfNames);
        System.out.println("Base64编码后的ZIP字符串：" + base64Zip);
    }
}